<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2018/10/25
 * Time: 17:25
 */

namespace app\common\model;

use app\common\lib\exception\ApiException;
use think\Config;
use XznsTools\cache\CacheManage;
use think\Model;

/**
 * 数据操作基础类
 * Class BaseCache
 * @package app\common\model
 */
class BaseCache extends Model
{
    /**
     * 缓存模型
     * @var string
     */
    protected $cacheModel = '';
    /**
     * 缓存id键名 为空时不更新
     * @var string
     */
    protected $cacheIdKey = '';
    /**
     * 每页显示数量
     * @var int
     */
    protected $pageLimit = null;

    /**
     * 页数
     * @var null
     */
    protected $page = null;

    protected $cache_on = 1;

    protected $dataCache = [];

    /**
     * BaseCache constructor.
     * @param array $data
     */
    public function __construct($data = [])
    {
        parent::__construct($data);
    }

    /**
     * 设置页数
     * @param $page
     * @return void
     */
    public function setPage($page)
    {
        $this->page = $page;
    }

    /**
     * 添加数据
     * @param $data
     * @return int|string
     */
    public function insertData($data)
    {
        try
        {
            $id = $this->insertGetId($data);
        }
        catch (\Exception $e)
        {
            $id = 0;
        }
        return $id;
    }

    /**
     *  监听数据更新后 -- 写入缓存
     */
    protected static function init()
    {
        (static::class)::event('after_update', function ($uModel)
        {   // after_update 更新之后执行
            if (!empty($uModel->cacheIdKey) && isset($uModel->updateWhere[$uModel->cacheIdKey]) && !empty($uModel->updateWhere[$uModel->cacheIdKey]))
            {   // 判断缓存的ID是否存在  并且 更新条件存在缓存ID
                CacheManage::getInstance()
                    ->setCacheConfig($uModel->cacheModel, $uModel->updateWhere[$uModel->cacheIdKey])
                    ->setCache($uModel->data, 'details', true);
                // 全局存储缓存KEY
                global $updateCacheKey;
                if (empty($updateCacheKey)) $updateCacheKey = [];
                $updateCacheKey[] = [
                    'cache_model' => $uModel->cacheModel,
                    'id' => $uModel->updateWhere[$uModel->cacheIdKey]
                ];
            }
        });
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @throws ApiException
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        throw new ApiException('getInfoByIdsInData方法未定义', 200, config('code.error'));
    }

    /**
     * 批量通过ID获取缓存数据
     * @param $cids
     * @param array $field
     * @return array
     * @throws \Exception
     */
    public function batchGetInfoByIds($cids, $field = [])
    {
        $cids = is_array($cids) ? $cids : explode(',', $cids);

        $resData = [];
        $cids2 = [];
        if (empty($field))
        { // empty
            foreach ($cids as $cid)
            {
                if (isset($this->dataCache[$cid]))
                {
                    $resData[$cid] = $this->dataCache[$cid];
                } else
                {
                    $cids2[] = $cid;
                }
            }
        } else
        {
            $cids2 = $cids;
        }

        if (empty($cids2))
        {
            return $resData;
        }

        $data = CacheManage::getInstance()->setCacheConfig($this->cacheModel)
            ->batchGetCache($cids2, function ($ids)
            {
                return $this->getInfoByIdsInData($ids, null, null);
            }, $field, 'list_details');

        if (empty($field))
        {
            foreach ($data as $id => $datum)
            {
                $resData[$id] = $datum;
                $this->dataCache[$id] = $datum;
            }
        } else
        {
            $resData = $data;
        }

        return $resData;
    }

    /**
     * 获取单条数据缓存
     * @param $cid
     * @param array $field
     * @return mixed
     * @throws \Exception
     */
    public function getInfoById($cid, $field = [])
    {
        $data = $this->batchGetInfoByIds($cid, $field);

        return current($data);
    }

    /**
     * 获取分页数据
     * @param $id
     * @param string $sortKey 排序的键
     * @param array $field
     * @param int $type 分页数据状态
     * @param string $sort 排序方式
     * @param int $isSortNum
     * @param string $listKey
     * @param string $detailsKey
     * @return array|mixed
     * @throws \Exception
     */
    public function getListPage($id, $sortKey = 'id', $field = [], int $type = 0, $sort = 'desc', $isSortNum = 1, $listKey = 'list', $detailsKey = 'list_details')
    {
        $page = $this->page ?: input('page/d', 1);
        $sort = strtolower($sort) == 'desc' ? 'desc' : 'asc';
        $limit = $this->pageLimit ?: Config::get('paginate.list_rows');

        $data = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $id)
            ->setPage($page)
            ->setPageSize($limit)
            ->setSort($sort)
            ->setListKeyType($type)// 类型 用于分页 例如 0全部 1待支付 已支付 //
            ->getListPage(function ($ids = [], $isCache = true, $sortType = 'desc') use ($id, $type)
            {
                if ($isCache)
                { // 开启了缓存
                    return $this->getInfoByIdsInData($ids, [$id, $type], $sortType);
                } else
                { // 没开启缓存
                    return $this->getPaginateInData([$id, $type], $sortType);
                }
            }, $sortKey, $field, $isSortNum, $listKey, $detailsKey);

        return $data;
    }

    /**
     * 未开启缓存从数据库获取分页数据
     * @param array $type 分页数据状态
     * @param string $sortType 排序方式
     * @throws ApiException
     */
    public function getPaginateInData($type, $sortType)
    {
        throw new ApiException('getInfoByIdsInData方法未定义', 200, config('code.error'));
    }

    /**
     * 向分页list里面新增数据
     * @param int $id 缓存KEY的ID
     * @param array $data 新增的数据 ['id'=>15000排序]
     * @param int $type 分页数据状态 例如 0全部 1待审核...啥的
     * @param string $listKey
     * @throws \Exception
     */
    public function listDataAdd($id, array $data, int $type = 0, $listKey = 'list')
    {
        CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $id)
            ->listAdd($data, $type, $listKey);
    }

    /**
     * @param int $id 缓存KEY的ID
     * @param array $rmIds 删除的id  [12,13]
     * @param int $type 分页数据状态 例如 0全部 1待审核...啥的
     * @param string $listKey
     * @throws \Exception
     */
    public function listDataDel($id, array $rmIds, int $type = 0, $listKey = 'list')
    {
        $cacheModel = CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->setListKeyType($type);
        foreach ($rmIds as $rmId)
        {
            $cacheModel->delJudge($rmId, $listKey);
        }
    }

    /**
     * 缓存分页list数据状态切换
     * @param int $id 缓存KEY的ID
     * @param string|array $changeIds 要切换状态的数据IDs
     * @param int $startType 起始状态
     * @param int $endType 结束状态
     * @param int $chengeType 切换方式  1移动（从1集合移动到2集合）2 拷贝（从1集合，复制到2集合）
     * @param string $listKey
     * @throws \Exception
     */
    public function listTypeChange(int $id, $changeIds, int $startType, int $endType, int $chengeType = 1, $listKey = 'list')
    {
        CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $id)
            ->listTypeChange($changeIds, $startType, $endType, $chengeType, $listKey);
    }
}
